package com.bilibili.movies.controller;

import com.bilibili.movies.entity.Comment;
import com.bilibili.movies.entity.Foot;
import com.bilibili.movies.entity.Movie;
import com.bilibili.movies.entity.User;
import com.bilibili.movies.entity.dto.MovieDto;
import com.bilibili.movies.service.CommentsServiceImpl;
import com.bilibili.movies.service.FootServiceImpl;
import com.bilibili.movies.service.MovieServiceImpl;
import com.bilibili.movies.service.UserService;
import com.bilibili.movies.util.NonStaticResourceHttpRequestHandler;
import com.bilibili.movies.util.Result;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;


    @RestController
    @RequestMapping("/user")
    public class MovieController {
        @Value("${video.path}")
        private String videoPath;
        @Value("${static.path}")
        private String staticPath;
        @Resource
        MovieServiceImpl movie;
        @Resource
        UserService userService;
        @Resource
        CommentsServiceImpl comments;
        @Resource
        NonStaticResourceHttpRequestHandler nonStaticResourceHttpRequestHandler;
        @Resource
        FootServiceImpl userFoot;
        @Resource
        RedisTemplate<Object,Object> redisTemplate;

        @GetMapping("/getnowlist")//正在热映,redis(key==hotting)
        public Result getNowList() {
            List<Movie> list = (List<Movie>) redisTemplate.opsForValue().get("hotting");
            if(list==null){
                list = movie.lambdaQuery().eq(Movie::getHot, 1).list();
                redisTemplate.opsForValue().set("hotting",list);
            }



            return Result.suceess(list);

        }

        @GetMapping("/getrecentlist")//最近热门电影(hot=2),redis(key==recentHot)
        public Result getRecentList() {
            List<Movie> list = (List<Movie>) redisTemplate.opsForValue().get("recentHot");
            if(list==null){
                list = movie.lambdaQuery().eq(Movie::getHot, 2).list();
                redisTemplate.opsForValue().set("recentHot",list);
            }
            return Result.suceess(list);

        }

        @GetMapping("/getranklist")//一周热映(hot=3),redis(key==weekHot)
        public Result getRankList() {
            List<Movie> list = (List<Movie>) redisTemplate.opsForValue().get("weekHot");
            if(list==null){
                list = movie.lambdaQuery().eq(Movie::getHot, 3).list();
                redisTemplate.opsForValue().set("weekHot",list);
            }



            return Result.suceess(list);


        }

        @GetMapping("/getmovie")//电影详情
        public Result getSingleMovie(Integer id) {

            Movie mo = movie.lambdaQuery().eq(Movie::getId, id).one();
            List<Comment> list = comments.lambdaQuery().eq(Comment::getMovcId, id).list();

            for (Comment comment : list) {
                User one = userService.lambdaQuery().eq(User::getId, comment.getUsecId()).one();
                comment.setName(one.getEmail());
            }
            MovieDto mdto = new MovieDto((ArrayList<Comment>) list);
            BeanUtils.copyProperties(mo, mdto);
            return Result.suceess(mdto);
        }

        @PostMapping("/submitComment")//提交评论
        public Result submitComment(@RequestBody Comment comment) {
            comment.setTime(LocalDate.now());
            comments.save(comment);
            return Result.suceess(null);
        }

        @GetMapping("/search")//搜索
        public Result search(String searchText) {

            List<Movie> list = movie.lambdaQuery().like(Movie::getName, searchText).list();
            if (list == null) {
                return Result.error("暂无该影片");
            } else {

                return Result.suceess(list);
            }


        }

        @RequestMapping("/getVideo")//播放视频
        public void getVideo(String path, HttpServletRequest request, HttpServletResponse response) {

            try {
                File file = new File(videoPath + path);
                if (file.exists()) {
                    request.setAttribute(NonStaticResourceHttpRequestHandler.ATTR_FILE, videoPath + path);
                    nonStaticResourceHttpRequestHandler.handleRequest(request, response);


                } else {
                    response.setStatus(HttpServletResponse.SC_NOT_FOUND);
                    response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
                }
            } catch (Exception e) {

            }
        }
        @GetMapping("/addFoot")//用户足迹
        public void addFoot(Foot foot,HttpServletRequest request){
            LocalDate now = LocalDate.now();
            Foot one = userFoot.lambdaQuery().eq(Foot::getTime, now)
                    .eq(Foot::getMovieId, foot.getMovieId())
                    .eq(Foot::getUserId, foot.getUserId()).one();
            if(one==null){
                Movie movie1 = movie.lambdaQuery().eq(Movie::getId, foot.getMovieId()).one();
                foot.setMovieName(movie1.getName());
                foot.setTime(LocalDate.now());

                userFoot.save(foot);
            }


        }
        @GetMapping("/getFoots")
        public Result getFoots(Integer id){

            List<Foot> list = userFoot.lambdaQuery().eq(Foot::getUserId, id).orderByDesc(Foot::getTime).list();
            return Result.suceess(list);

        }

        @PostMapping("/upload")//controller上传电影视频
        public Result upload(MultipartFile file ) {

            String filename = file.getOriginalFilename();
            //插入到数据库
            try {
                file.transferTo(new File(videoPath + filename));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return Result.suceess(filename);
        }
        @PostMapping("/addMovie")//controller上传电影信息
        public Result addMovie(@RequestBody Movie form ) {
            this.movie.save(form);
            ValueOperations<Object, Object> Str = redisTemplate.opsForValue();
            if(form.getHot()==1){
                ToSet("hotting",Str,form);
            } else if (form.getHot()==2) {
                ToSet("recentHot",Str,form);
            }else {
                ToSet("weekHot",Str,form);
            }


            return Result.suceess("添加成功");
        }
        @PostMapping("/uploadPoster")//controller上传电影海报(或者用户上传自己的头像)
        public Result uploadPoster(MultipartFile file,Integer id) {
            String filename = file.getOriginalFilename();
           if(id!=null){//用户头像（有待优化，跟新时删除已有的用户头像）
               User one = userService.lambdaQuery().eq(User::getId, id).one();
               filename=id+".jpg";
               one.setAvatar(filename);

               userService.updateById(one);
           }
            try {
                file.transferTo(new File(staticPath + filename));
            } catch (IOException e) {
                throw new RuntimeException(e);
            }


            return Result.suceess(filename);
        }
        @GetMapping("/download")
        public void download(String name, HttpServletResponse response){

            try {
                FileInputStream inputStream=new FileInputStream(new File(staticPath+name));
                ServletOutputStream outputStream = response.getOutputStream();
                response.setContentType("image/jpeg");
                byte []arr=new byte[1024];
                int len=0;
                while((len= inputStream.read(arr))!=-1){
                    outputStream.write(arr,0,len);
                    outputStream.flush();
                }
                outputStream.close();
                inputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }



            // return Result.suceess(null);
        }


        private void ToSet(String key, ValueOperations<Object, Object> Str,Movie movie){
            List<Movie> list = (List<Movie>) Str.get(key);
            list.add(movie);
            Str.set(key,list);
        }




    }


